﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using Yelper.Web.Models;
using Yelper.Web.Helpers;
using Yelper.Web.Resources;
using System.Security.Cryptography;

namespace Yelper.Web.Controllers {

    public class AccountController : Controller {
        
        
       
        public ActionResult LogOn() {
            return RedirectToAction("Index", "Home");
        }

        [HttpPost]
        public ActionResult LogOn(LogOnModel model) {
            if (ModelState.IsValid) {

                using (yelperEntities entities = new yelperEntities()) {

                    var user = entities.Users.Where(u => u.Username == model.LogonUsername).SingleOrDefault();

                    if (user == null || !user.Activated)
                        return RedirectToAction("Index", "Home");

                    if (user.Password.SequenceEqual(AuthenticationHelper.StringToSHA384(model.Password)))
                        FormsAuthentication.SetAuthCookie(model.LogonUsername, false);

                    return RedirectToAction("Index", "Home");

                }
            }
            return RedirectToAction("Index", "Home");
        }

        public ActionResult Logout() {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index", "Home");
        }

        public ActionResult Register() {
            return View();
        }

        [HttpPost]
        public ActionResult Register(User model) {
            if (ModelState.IsValid) {
                using (yelperEntities entities = new yelperEntities()) {
                    model.Password = AuthenticationHelper.StringToSHA384(model.PlainTextPassword);
                    model.Created = DateTime.UtcNow;
                    model.Activated = false;
                    model.GUID = Guid.NewGuid().ToString();
                    entities.AddToUsers(model);
                    entities.SaveChanges();
                }
                (new EmailHelper()).SendEmail(
                    model.Email, EmailTemplates.ConfirmSubject,
                    string.Format(EmailTemplates.ConfirmBody, 
                    model.Username, model.GUID));
                ViewData["succes"] = true;
            }
            return View();
        }

        public ActionResult Confirm(string guid) {
            using (yelperEntities entities = new yelperEntities()) {
                var users = entities.Users.Where(x => x.GUID == guid);
                if (users.Count() != 1) return HttpNotFound();
                User user = users.Single();
                user.GUID = null;
                user.Activated = true;
                entities.SaveChanges();
                FormsAuthentication.SetAuthCookie(user.Username, false);
            }
            return RedirectToAction("Profile");
        }

        [Authorize]
        public ActionResult Profile() {
            string username = User.Identity.Name; User model;
            using (yelperEntities entities = new yelperEntities()) {
                model = entities.Users.Where(x => x.Username == username).SingleOrDefault();
            }
            return View(model);
        }

        [Authorize]
        [HttpPost]
        public ActionResult Profile(User model) {
            string username = User.Identity.Name; User user;
            string imagename = "";
            string[] mimetypes = new string[] { "image/gif", "image/jpeg", 
                "image/pjpeg", "image/png", "image/x-png" };
            bool GotToProfileImageCrop = false;
            if (Request.Files.Count == 1) {
                var file = Request.Files[0];
                if (file.ContentLength > 0) {
                    if (file.ContentLength <= 1024 * 1024) { // 1MB
                        if (mimetypes.Contains(file.ContentType)) {
                            imagename = Guid.NewGuid().ToString() + file.FileName.Substring(file.FileName.LastIndexOf('.') - 1);
                            string temppath = Server.MapPath("~/Content/ProfileImages/temp-" + imagename);
                            string finalpath = Server.MapPath("~/Content/ProfileImages/" + imagename);
                            file.SaveAs(temppath);
                            ImageHelper.ResizeImageIfTooWide(temppath, finalpath, 650);
                            if (System.IO.File.Exists(temppath)) System.IO.File.Delete(temppath);
                            GotToProfileImageCrop = true;
                        } else {
                            ModelState.AddModelError("upload", "The format of this file is not supported (use png, gif or jpg).");
                        }
                    } else {
                        ModelState.AddModelError("upload", "This file is too big (max. 1MB).");
                    }
                }
            }
            if (ModelState.IsValidField("upload") && 
                ModelState.IsValidField("Website") && 
                ModelState.IsValidField("Bio")) {
                using (yelperEntities entities = new yelperEntities()) {
                    user = entities.Users.Where(x => x.Username == username).SingleOrDefault();
                    user.Website = model.Website;
                    user.Bio = model.Bio;
                    if (imagename != "") {
                        string oldimg = user.ProfilePicture;
                        string path = Server.MapPath("~/Content/ProfileImages/" + oldimg);
                        if(System.IO.File.Exists(path)) System.IO.File.Delete(path);
                        user.ProfilePicture = imagename;
                    }
                    entities.SaveChanges();
                }
                if (GotToProfileImageCrop) {
                    return Redirect(Url.Action("ProfileImageCrop") + "#crop");
                } else {
                    ViewData["saved"] = true;
                    return View(user);
                }
            }else{
                string usrnm = User.Identity.Name; User usr;
                using (yelperEntities entities = new yelperEntities()) {
                    usr = entities.Users.Where(x => x.Username == usrnm).SingleOrDefault();
                }
                model.Username = usr.Username;
                model.ProfilePicture = usr.ProfilePicture;
                return View(model);
            }
        }

        [Authorize]
        public ActionResult ProfileImageCrop() {
            string username = User.Identity.Name;
            string imagename;
            using (yelperEntities entities = new yelperEntities()) {
                imagename = entities.Users.Where(x => x.Username == username).Single().ProfilePicture;
            }
            return View((object)imagename);
        }

        [Authorize]
        [HttpPost]
        public ActionResult ProfileImageCrop(FormCollection form) {
            string username = User.Identity.Name;
            string imagename;
            using (yelperEntities entities = new yelperEntities()) {
                imagename = entities.Users.Where(q => q.Username == username).Single().ProfilePicture;
            }
            imagename = Server.MapPath("~/Content/ProfileImages/" + imagename);
            System.IO.File.Move(imagename, imagename + "tmp");

            int x = 0, y = 0, w = 0, h = 0;
            if (null != form["x"] && "" != form["x"]) x = int.Parse(form["x"]);
            if (null != form["y"] && "" != form["y"]) y = int.Parse(form["y"]);
            if (null != form["w"] && "" != form["w"]) w = int.Parse(form["w"]);
            if (null != form["h"] && "" != form["h"]) h = int.Parse(form["h"]);

            ImageHelper.CropAndResizeTo80(imagename + "tmp", imagename, x, y, w, h);
            System.IO.File.Delete(imagename + "tmp");

            return RedirectToAction("Profile");
        }

        public ActionResult ForgotPwd() {
            return View();
        }

        [HttpPost]
        public ActionResult ForgotPwd(ForgotPasswordModel model) {
            if (ModelState.IsValid) {
                string newpwd = "";
                using (yelperEntities entities = new yelperEntities()) {
                    string username = model.Username;
                    string email = model.Email;
                    var users = entities.Users.Where(x => x.Email == email && x.Username == username);
                    if (users.Count() != 1) {
                        ModelState.AddModelError("Email", "Username/email combo not found!");
                    } else {
                        User user = users.Single();
                        newpwd = CreateRandomPassword(12);
                        user.Password = AuthenticationHelper.StringToSHA384(newpwd);
                        entities.SaveChanges();
                    }
                }
                if ("" != newpwd) {
                    (new EmailHelper()).SendEmail(
                        model.Email, EmailTemplates.ForgotPwdSubject,
                        string.Format(EmailTemplates.ForgotPwdBody, newpwd));
                    ViewData["success"] = true;
                }
            }
            return View(model);
        }

        private string CreateRandomPassword(int passwordLength) {
            
            string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789!@$?_-";

            Byte[] randomBytes = new Byte[passwordLength];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            rng.GetBytes(randomBytes);
            char[] chars = new char[passwordLength];
            int allowedCharCount = allowedChars.Length;

            for (int i = 0; i < passwordLength; i++) {
                chars[i] = allowedChars[(int)randomBytes[i] % allowedCharCount];
            }

            return new string(chars);
        }

        [Authorize]
        public ActionResult ChangePwd() {
            return View();
        }

        [Authorize]
        [HttpPost]
        public ActionResult ChangePwd(ChangePasswordModel model) {
            if (ModelState.IsValid) {
                using (yelperEntities entities = new yelperEntities()) {
                    String username = User.Identity.Name;
                    var pwd = AuthenticationHelper.StringToSHA384(model.Password);
                    User usr = entities.Users.Where(x => x.Username == username).First();
                    if (usr.Password.SequenceEqual(pwd)) {
                        var newpwd = AuthenticationHelper.StringToSHA384(model.NewPassword);
                        usr.Password = newpwd;
                        entities.SaveChanges();
                        ViewData["success"] = true;
                    } else {
                        ModelState.AddModelError("Password", "Wrong password!");
                    }
                }
            }
            return View(model);
        }

    }
}
